package cn.iyouthy.view.mask

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PixelFormat
import android.os.Bundle
import android.view.SurfaceHolder
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import cn.iyouthy.view.mask.databinding.ActivityMainBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.util.Random

class MainActivity : Activity(), LifecycleOwner, SurfaceHolder.Callback {
    private val random = Random()
    private val paint = Paint().apply {
        color = Color.WHITE
        isAntiAlias = true
    }

    data class Dimension(
        val width: Int,
        val height: Int
    )

    private val registry = LifecycleRegistry(this)

    override val lifecycle: Lifecycle = registry
    private val bitmap = MutableStateFlow<Bitmap?>(null)
    private val dimension = MutableStateFlow<Dimension?>(null)
    private val mask = combine(
        bitmap,
        dimension.filterNotNull(),
        ::Pair
    ).map { (bitmap, dimension) ->
        bitmap?.let {
            val (nw, nh) = dimension
            Bitmap.createScaledBitmap(it, nw, nh, false)
        }?.let { BitmapMask(it) }
    }.stateIn(lifecycleScope, SharingStarted.Lazily, null)

    private val loop = MutableSharedFlow<Unit>()


    private fun prepareBitmap() {
        lifecycleScope.launch(Dispatchers.IO) {
            bitmap.update {
                assets.open("mask.webp").use { ips ->
                    val options = BitmapFactory.Options()
                    options.inPreferredConfig = Bitmap.Config.ALPHA_8
                    BitmapFactory.decodeStream(ips, null, options)
                }
            }
        }
    }

    private val binding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
        setContentView(binding.root)

        binding.svCanvas.holder.addCallback(this)
        binding.svCanvas.holder.setFormat(PixelFormat.TRANSPARENT)

        prepareBitmap()

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
            }
        }

        lifecycleScope.launch(Dispatchers.Default) {
            repeatOnLifecycle(Lifecycle.State.RESUMED) {
                while (true) {
                    delay(16)
                    loop.emit(Unit)
                }
            }
        }

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.RESUMED) {
                combine(
                    mask,
                    loop,
                    ::Pair
                ).collectLatest { (mask) ->
                    drawFrame(binding.svCanvas.holder, mask)
                }
            }
        }
    }

    override fun onStart() {
        super.onStart()
        registry.handleLifecycleEvent(Lifecycle.Event.ON_START)
    }

    override fun onResume() {
        super.onResume()
        registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
    }

    override fun onPause() {
        super.onPause()
        registry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    }

    override fun onStop() {
        super.onStop()
        registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
    }

    override fun onDestroy() {
        super.onDestroy()
        registry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        drawFrame(holder)
    }

    private fun drawFrame(holder: SurfaceHolder, bitmapMask: BitmapMask? = null) {
        val canvas = holder.lockCanvas() ?: return
        dimension.update { Dimension(canvas.width, canvas.height) }
        canvas.drawColor(Color.BLACK)
        for (i in 1..50) {
            paint.strokeWidth = (random.nextInt(3) + 1).toFloat()
            canvas.drawPoint(
                random.nextInt(binding.svCanvas.width).toFloat(),
                random.nextInt(binding.svCanvas.height).toFloat(),
                paint
            )
        }
        bitmapMask?.compose(canvas)
        holder.unlockCanvasAndPost(canvas)
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        dimension.update { Dimension(width, height) }
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {}

}
